package com.ibmeeting.modules.security.service.impl;

import com.ibmeeting.domain.event.AccessLogEvent;
import com.ibmeeting.exception.BusinessException;
import com.ibmeeting.modules.security.service.AuthService;
import com.ibmeeting.modules.security.service.dto.AuthUserDto;
import com.ibmeeting.modules.system.domain.UUser;
import com.ibmeeting.modules.system.service.UUserService;
import com.ibmeeting.service.SysConfigService;
import com.ibmeeting.utils.*;
import com.ibmeeting.utils.constant.CacheConstants;
import com.ibmeeting.utils.constant.Constants;
import com.ibmeeting.utils.enums.UserTypeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class AuthServiceImpl implements AuthService {


    private final SysConfigService sysConfigService;
    private final RedisUtils redisUtils;
    private final UUserService userService;


    @Override
    public void register(AuthUserDto authUser) throws Exception {


        if (!("true".equals(sysConfigService.selectConfigByKey("sys.account.registerUser")))) {
            throw new RuntimeException("当前系统没有开启注册功能！");
        }

        String phone = authUser.getPhone();
        String email = authUser.getEmail();
        String phoneCode = authUser.getPhoneCode();
        String emailCode = authUser.getEmailCode();

        // 校验用户类型是否存在（代码是为了适配多端登录）
        String userType = UserTypeEnum.getUserType(authUser.getUserType()).getUserType();


        // 校验验证码
       validateCaptcha(phone, phoneCode, email, emailCode, authUser.getUuid());


       // 随机生成一个昵称
        String username = phone;
        String nickName = StringUtils.generateByPhoneTail(phone);


        UUser sysUser = new UUser();
        sysUser.setUserName(username);
        sysUser.setNickName(nickName);
//        sysUser.setPassword(BCrypt.hashpw(password));
        sysUser.setUserType(userType);

        if (!userService.checkUserUnique(sysUser)) {
            throw new RuntimeException("新增用户'" + username + "'失败，登录账号已存在");
//            throw new UserException("user.register.save.error", username);
        }
        boolean save = userService.save(sysUser);

        if (!save) {
            throw new RuntimeException("注册失败,请联系系统管理人员");
        }
        recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));


        //

    }


    /**
     * 校验验证码
     *
     * @param username 用户名
     * @param code     验证码
     * @param uuid     唯一标识
     */
    public void validateCaptcha(String phone, String phoneCode, String email, String emailCode,String uuid) throws Exception {



        String phoneRedisKey = CacheConstants.CAPTCHA_CODE_KEY + phone;
        String emailRedisKey = CacheConstants.CAPTCHA_CODE_KEY + email;


        String smsCodeFromDB = redisUtils.get(phoneRedisKey, String.class);
        String emailCodeFromDB = redisUtils.get(emailRedisKey, String.class);

        redisUtils.del(phoneRedisKey, emailRedisKey);

        String username = phone;

        // 手机号和邮箱都是唯一的
        // 缓存中是否存在
        if (smsCodeFromDB == null || emailCodeFromDB == null) {
            recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
            throw new RuntimeException("验证码失效");
        }

        // 判断验证码是否正确
        if (!phoneCode.equalsIgnoreCase(smsCodeFromDB) || emailCode.equalsIgnoreCase(emailCodeFromDB)) {
            recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
            throw new RuntimeException("验证码错误");
        }
    }


    /**
     * 记录登录信息
     *
     * @param username 用户名
     * @param status   状态
     * @param message  消息内容
     * @return
     */
    private void recordLogininfor(String username, String status, String message) {
        AccessLogEvent accessLogEvent = new AccessLogEvent();
        accessLogEvent.setUsername(username);
        accessLogEvent.setStatus(status);
        accessLogEvent.setMessage(message);
        accessLogEvent.setRequest(ServletUtils.getRequest());
        SpringBeanHolder.context().publishEvent(accessLogEvent);
    }
}
